home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
network
/
ka9q
/
nhclb120.zoo
/
dirutil.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-20
|
16KB
|
693 lines
/* dirutil.c - MS-DOS directory reading routines
*
* Bdale Garbee, N3EUA, Dave Trulli, NN2Z, and Phil Karn, KA9Q
* Directory sorting by Mike Chepponis, K3MC
* adapted for ATARI ST & cleaned up by Rob Janssen, PE1CHL
* adapted for Lattice C by Walter Doerr, DG2KK
*/
#include <stdio.h>
static void dir_sort(), format_dir(),format_fname(), diskfree(), free_clist();
static getdir_nosort();
static getdir();
#ifndef GNUC
#define Fsetdta(a) bdos(SET_DTA,a)
#endif
#ifndef LATTICE
#include <ctype.h> /* DG2KK: force Lattice to use library func. */
#endif
#if defined( LATTICE ) || ( defined(ATARI_ST) && defined(GNUC))
#define S_IJHID 2
#define S_IJSYS 4
#define S_IJDIR 0x10
struct stat {
char st_mode; /* that's all we need */
};
#else /* not LATTICE */
#ifdef __TURBOC__
#include <dos.h>
#include <sys\stat.h>
#else /* not LATTICE and not TURBOC */
#include <stat.h>
#endif
#endif
#ifdef MSDOS
#define IS_ERROR == -1 /* error return from MSDOS */
#endif
#ifdef __TURBOC__
#define ST_RDONLY 0x01 /* Read only attribute */
#define ST_HIDDEN 0x02 /* Hidden file */
#define ST_SYSTEM 0x04 /* System file */
#define ST_LABEL 0x08 /* Volume label */
#define ST_DIRECT 0x10 /* Directory */
#define ST_ARCH 0x20 /* Archive */
int dos(unsigned ah,
unsigned bx,
unsigned cx,
void *dx,
unsigned si,
unsigned di)
{
union REGS regs;
regs.h.ah = ah;
regs.x.bx = bx;
regs.x.cx = cx;
regs.x.dx = dx;
regs.x.si = si;
regs.x.di = di;
intdos(®s, ®s);
if (regs.x.cflag) return -1;
return 0;
}
#define bdos(x, y) bdos(x, (unsigned) y, 0)
#endif /* TURBOC */
#ifdef ATARI_ST
#define IS_ERROR < 0 /* error return from gemdos */
#include <osbind.h> /* os interface defines */
#define bdos gemdos /* Atari OS call */
#ifndef GNUC
#define dos(a,b,c,d,e,f) gemdos(a,d,c) /* only valid for FIND func */
#else
#define dos(a,b,c,d,e,f) gnudos(a,d,c)
short gnudos();
#endif
#define st_attr st_mode /* what's in a name? */
#define ST_HIDDEN S_IJHID /* Hidden from search */
#define ST_SYSTEM S_IJSYS /* System, hidden from search */
#define ST_DIRECT S_IJDIR /* Directory */
#endif
#include "global.h"
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE !(FALSE)
#endif
#define REGFILE (ST_HIDDEN|ST_SYSTEM|ST_DIRECT)
#define SET_DTA 0x1a
#define FIND_FIRST 0x4e
#define FIND_NEXT 0x4f
struct dirent {
char rsvd[21];
char attr;
short ftime;
short fdate;
long fsize;
char fname[13];
};
#define NULLENT (struct dirent *)0
struct dirsort {
struct dirsort *prev;
struct dirsort *next;
struct dirent *direntry;
};
#define NULLSORT (struct dirsort *)0
/* Create a directory listing in a temp file and return the resulting file
* descriptor. If full == 1, give a full listing; else return just a list
* of names.
*/
FILE *
dir(path,full)
char *path;
int full;
{
FILE *fp,*tmpfile();
if ((fp = tmpfile()) != NULLFILE)
{
getdir(path,full,fp);
/* This should be rewind(), but Aztec doesn't have it */
#if (ATARI_ST && MWC)
vseek(fp,0L,0);
#else
fseek(fp,0L,0);
#endif
}
return fp;
}
/* wildcard filename lookup */
filedir(name,times,ret_str)
char *name;
int times;
char *ret_str;
{
register char *cp,*cp1;
static struct dirent sbuf;
Fsetdta(&sbuf); /* Set disk transfer address */
/* Find matching file */
if(dos(times == 0 ? FIND_FIRST:FIND_NEXT,0,REGFILE,name,0,0) IS_ERROR)
sbuf.fname[0] = '\0';
/* Copy result to output, forcing to lower case */
for(cp = ret_str,cp1 = sbuf.fname; cp1 < &sbuf.fname[13] && *cp1 != '\0';)
*cp++ = (char)tolower(*cp1++); /* DG2KK: added (char) */
*cp = '\0';
}
/* Change working directory */
docd(argc,argv)
int argc;
char *argv[];
{
char dirname[128];
#ifdef MSDOS
char *getcwd();
#endif
if(argc > 1){
if(chdir(argv[1]) IS_ERROR){
printf("Can't change directory\n");
return 1;
}
}
#ifdef MSDOS
if(getcwd(dirname,0) != NULLCHAR){
printf("\\%s\n",dirname);
}
#endif
#ifdef ATARI_ST
if (Dgetpath(dirname,0) == 0){
printf("%c:%s%s\n",(char) Dgetdrv()+'A',
(*dirname? "" : "\\"),dirname);
}
#endif
return 0;
}
/* List directory to console. [-/]w option selects "wide" format */
dodir(argc,argv)
int argc;
char *argv[];
{
char *path;
int full = 1;
if (argc > 1 &&
(argv[1][0] == '-' || argv[1][0] == '/') && argv[1][1] == 'w')
{
full = -1;
argv++;
argc--;
}
if(argc >= 2){
path = argv[1];
} else {
path = "*.*";
}
getdir(path,full,stdout);
return 0;
}
/* do a directory list to the stream
* full = 0 -> short form, 1 is long, -1 is multi-column short
*/
static
getdir(path,full,file)
char *path;
int full;
FILE *file;
{
struct dirent sbuf;
struct stat statbuf;
char *cp,*cp1; /* !!!!!!! was: register */
char dirtmp[20];
int command = FIND_FIRST;
int i = 0;
int cflag = 0;
int n = 0;
char line_buf[50]; /* for long dirlist */
struct dirsort *head, *here, *new;
struct dirent *de;
int malloc_lost = FALSE;
/* Root directory is a special case */
if(path == NULLCHAR || *path == '\0' || strcmp(path,"\\") == 0)
path = "\\*.*";
/* If arg is a directory, append "\*.*" to it.
* This is tricky, since the "stat" system call actually
* calls the DOS "find matching file" function. The stat
* call therefore returns the attributes for the first matching
* entry in the directory. If the arg already ends in *.*,
* stat will match the . entry in the directory and indicate
* that the argument is a valid directory name. Hence the
* heuristic check for '*' in the file name. Kludge...
*/
#ifdef __TURBOC__
else if(stat(path,&statbuf) != -1
&& (statbuf.st_mode & S_IFDIR)
&& index(path,'*') == NULLCHAR) {
#else
else if(index(path,'*') == NULLCHAR
&& stat(path,&statbuf) != -1
&& (statbuf.st_attr & ST_DIRECT)) {
#endif
if((cp = malloc(strlen(path) + 10)) == NULLCHAR)
return -1;
sprintf(cp,"%s%c%s",path,'\\',"*.*");
path = cp;
cflag = 1;
}
head = NULLSORT; /* No head of chain yet... */
for(;;){
Fsetdta(&sbuf); /* Set disk transfer address */
if(dos(command, 0, REGFILE, path, 0, 0) IS_ERROR)
break;
command = FIND_NEXT; /* Got first one already... */
if(sbuf.fname[0] != '.'){
/* nuke "." and ".." */
n++; /* One more entry */
new = (struct dirsort *) malloc(sizeof(struct dirsort));
if(new == NULLSORT)
malloc_lost = TRUE;
de = (struct dirent *)malloc(sizeof(struct dirent));
if(de == NULLENT)
malloc_lost = TRUE;
if(malloc_lost){
/* Clean up and call other routine */
if(new)free(new);
free_clist(head);
return getdir_nosort(path,full,file);
}
*de = sbuf; /* Copy contents of directory entry struct */
/* Fix up names for easier sorting... pain! */
strcpy(de->fname," "); /* 11 blanks */
cp = sbuf.fname;
cp1 = de->fname;
do *cp1++ = *cp++; while (*cp && *cp != '.');
if(*cp++){
/* If there is an extension */
cp1 = &(de->fname[8]);
do *cp1++ = *cp++; while (*cp);
}
if(!(int)head){
/* Make the first one */
here = head = new;
head->prev = head->next = NULLSORT;
} else {
/* Link on next one */
new->next = NULLSORT;
new->prev = here;
here->next = new;
here = new;
}
new->direntry = de;
} /* IF on "." */
} /* infinite FOR loop */
if(head)
dir_sort(head); /* Make a nice, sorted list */
here = head;
if(here)
if(full > 0){
do {
format_dir(line_buf,here->direntry);
fprintf(file,"%s%s",line_buf,(i^=1) ? " " : "\r\n");
} while (here = here->next);
if(i & 1)
fprintf(file,"\r\n");
}
else {
/* This is the short form */
do {
format_fname(dirtmp,here->direntry->fname,
here->direntry->attr);
fprintf(file,"%-15s%s",dirtmp,((full && ++i % 5)?"":"\r\n"));
} while (here = here->next);
if(full && i % 5)
fprintf(file,"\r\n");
}
/* Give back all the memory we temporarily needed... */
free_clist(head);
if(full > 0){
/* Provide additional information only on DIR */
if (isalpha(*path) && path[1] == ':') /* detect A: drivespec */
diskfree(file,*path & 0x1f,n);
else
diskfree(file,0,n);
}
if(cflag)
free(path);
return 0;
} /* getdir */
static
getdir_nosort(path,full,file)
char *path;
int